//
// Created by bjliuyong on 2021/7/11.
//

#ifndef JVM_CLASSLOADER_H
#define JVM_CLASSLOADER_H

#include "../adlc/arena.h"
#include "../memory/allocation.h"
#include "classFileStream.h"
#include "classFileParser.h"
#include "../oops/instanceKlass.h"
#include "../utilities/top.h"

class ClassPathEntry {

private:
    ClassPathEntry *_next;
public:
    // Next entry in class path
    ClassPathEntry *next() { return _next; }

    void set_next(ClassPathEntry *next) {
        // may have unlocked readers, so write atomically.
        //OrderAccess::release_store_ptr(&_next, next);
        this->_next = next;
    }

    virtual bool is_jar_file() = 0;

    virtual const char *name() = 0;

    virtual bool is_lazy();

    // Constructor
    ClassPathEntry();

    // Attempt to locate file_name through this class path entry.
    // Returns a class file parsing stream if successfull.
    virtual ClassFileStream *open_stream(const char *name) = 0;
};

class ClassPathDirEntry: public ClassPathEntry {
private:
    const char* _dir;           // Name of directory
public:
    bool is_jar_file()  { return false;  }
    const char* name()  { return _dir; }
    ClassPathDirEntry(const char* dir);
    ClassFileStream* open_stream(const char* name);
};

class ClassLoader : public AllStatic {
protected:
    // First entry in linked list of ClassPathEntry instances
    static ClassPathEntry *_first_entry;
    // Last entry in linked list of ClassPathEntry instances
    static ClassPathEntry *_last_entry;
public:
    //Initialization
    static void initialize();

    // Load individual .class file
    static InstanceKlass* load_classfile(const char* name);
};

#endif //JVM_CLASSLOADER_H
